/*
 * This file used to testing SM2/SM3/SM4 performance
 *
 * ===================================================
 *
 * author: linlh
 * date  : 2021.01.25
 * copyright: MIN-Group
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "openssl/evp.h"
#include "openssl/bn.h"
#include "openssl/ec.h"
#include "openssl/sm2.h"
#include "openssl/sm3.h"

#define BENCHMARK_TIME 10000 // 测试次数

// 这个函数的意思应该是Binary to String的意思
int b2s(char *bin, char *outs) {
    int i = 0;
    char tmpbuf[4];
    int iRet = 0;
    char *ptr = bin;
    for (i = 0; i < strlen(bin) / 2; i++) {
        memset(tmpbuf, 0x00, sizeof(tmpbuf));
        memcpy(tmpbuf, ptr, 2);
        ptr += 2;
        iRet = strtol(tmpbuf, NULL, 16);
#ifndef NO_DEBUG
// printf("the iRet =[%d]\n", iRet);
#endif

        memset(outs++, iRet, 1);
    }
    return i;
}

char *randstr(char *str, const int len) {
    srand(time(NULL));
    int i;
    for (i = 0; i < len; ++i) {
        switch ((rand() % 3)) {
        case 1:
            str[i] = 'A' + rand() % 26;
            break;
        case 2:
            str[i] = 'a' + rand() % 26;
            break;
        default:
            str[i] = '0' + rand() % 10;
            break;
        }
    }
    str[++i] = '\0';
    return str;
}

void benchsm3_hash(int size) {
	EVP_MD_CTX *ctx;
	const EVP_MD *md = NULL;
	unsigned char digest[32]; // 32 X 8 = 256 SM3算法的HASH结果为256位的
	
    clock_t start, finish;
    double totaltime;

    char *msg = (char *)malloc(size);
	memset(msg, 0, size);
	randstr(msg, size - 1);
    //char msg[] = "hello world";
    int length = strlen(msg);

	//printf("The msg tranlated length is [%d].\n", length);
   
    start = clock();
    for (int i = 0; i < BENCHMARK_TIME; ++i) {
        md = EVP_sm3();
        ctx = EVP_MD_CTX_create();
        EVP_DigestInit(ctx, md);
        length = strlen(msg); // HASH过后长度会变，因为用了同一个变量，所以这里要进行重新初始化

        EVP_DigestUpdate(ctx, msg, length);
        EVP_DigestFinal(ctx, digest, (unsigned *)&length);
    }
    finish = clock();
    totaltime = (double)(finish - start) / CLOCKS_PER_SEC / BENCHMARK_TIME;
    printf("SM3签名[%d]Bytes算法时间测试（测试次数：%d）: %f\n", size-1, BENCHMARK_TIME, totaltime);

	//printf("Msg:[%s], SM3 Digest:[", msg);
	//for (int i = 0; i < 32; ++i) printf("%02X", digest[i]);
	//printf("]\n");
	if (msg) free(msg);
}

int main(int argc, char *argv[]) {
	benchsm3_hash(9);
	benchsm3_hash(1025);
	benchsm3_hash(8193);
	return 0;
}
